#ifndef __MY_DATA__
#define __MY_DATA__

#include <unordered_map>
#include <pthread.h>
#include <vector>
#include "file_manage.hpp"
#include "config.hpp"

namespace cloud
{
    // 文件的备份信息
    struct BackupInfo
    {
        bool _packflag;        // 是否压缩标志
        size_t _fsize;         // 文件大小
        time_t _atime;         // 最后一次访问时间
        time_t _mtime;         // 最后一次修改时间
        std::string _realpath; // 文件实际存储路径
        std::string _packpath; // 压缩包存储路径
        std::string _url;      // url路径：用于path资源路径

        bool NewBackupInfo(const std::string &realpath)
        {
            filemanage fu(realpath);
            if (fu.Exists() == false)
            {
                std::cout << "new backupinfo: file not exists!\n";
                return false;
            }

            Config *config = cloud::Config::GetInstance();
            std::string pack_dir = config->GetPackDir();
            std::string packfile_suffix = config->GetPackFileSuffix();
            std::string download_prefix = config->GetDownloadPrefix();

            this->_packflag = false;
            this->_fsize = fu.FileSize();
            this->_atime = fu.LastATime();
            this->_mtime = fu.LastMTime();
            this->_realpath = realpath;
            // ./backdir/a.txt          ->          ./packdir/a.txt.lz
            this->_packpath = pack_dir + fu.FileName() + packfile_suffix;
            // ./backdir/a.txt          ->          ./download/a.txt
            this->_url = download_prefix + fu.FileName();

            return true;
        }
    };

    class DataManager
    {
    public:
        DataManager()
        {
            _backup_file = Config::GetInstance()->GetBackupFile();
            pthread_rwlock_init(&_rwlock, nullptr); // 初始化读写锁
            InitLoad();
        }
        ~DataManager()
        {
            pthread_rwlock_destroy(&_rwlock); // 销毁读写锁
        }
        // 每次数据新增或修改都要重新持久化存储，避免数据丢失
        // 持久化存储：将数据存储到文件中
        bool Storage()
        {
            // 1、获取所有数据
            std::vector<BackupInfo> array;
            GetAll(array);

            // 2、添加到Json::Value
            Json::Value root;
            for (int i = 0; i < array.size(); i++)
            {
                Json::Value item;
                item["packflag"] = array[i]._packflag;
                item["size"] = (Json::Value::Int64)array[i]._fsize;
                item["atime"] = array[i]._atime;
                item["mtime"] = array[i]._mtime;
                item["real_path"] = array[i]._realpath;
                item["pack_path"] = array[i]._packpath;
                item["url"] = array[i]._url;
                root.append(item); // 添加数组元素
            }

            // 3、对Json::Value序列化
            std::string body;
            Jsonmanage::Serialize(root, body);

            // 4、写文件
            filemanage fu(_backup_file);
            fu.SetContent(body);

            return true;
        }
        // 初始化加载，在每次系统重启都要加载以前的数据
        // 将文件中的数据读取出来
        bool InitLoad()
        {
            // 1、将数据文件中的数据读取出来
            std::string body;
            filemanage fu(_backup_file);
            if (fu.Exists() == false)
            {
                return true;
            }
            fu.GetContent(body);

            // 2、反序列化
            Json::Value root;
            cloud::Jsonmanage::UnSerialize(body, root);

            // 3、将反序列化得到的Json::Value中的数据添加到_table中
            for (int i = 0; i < root.size(); i++)
            {
                BackupInfo info;
                info._packflag = root[i]["packflag"].asBool();
                info._fsize = root[i]["size"].asInt64();
                info._atime = root[i]["atime"].asInt64();
                info._mtime = root[i]["mtime"].asInt64();
                info._packpath = root[i]["pack_path"].asString();
                info._realpath = root[i]["real_path"].asString();
                info._url = root[i]["url"].asString();
                Insert(info);
            }

            return true;
        }
        // 新增
        bool Insert(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[info._url] = info;
            pthread_rwlock_unlock(&_rwlock);
            Storage();

            return true;
        }
        // 修改
        bool Update(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[info._url] = info;
            pthread_rwlock_unlock(&_rwlock);
            Storage();

            return true;
        }
        // 获取url对应的信息
        bool GetOneByUrl(const std::string &url, BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.find(url);
            if (it == _table.end())
            {
                pthread_rwlock_unlock(&_rwlock);
                return false;
            }
            info = it->second;
            pthread_rwlock_unlock(&_rwlock);

            return true;
        }
        // 获取实际存放地址的对应信息
        bool GetOneByRealPath(const std::string &realpath, BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.begin();
            for (; it != _table.end(); it++)
            {
                if (it->second._realpath == realpath)
                {
                    info = it->second;
                    pthread_rwlock_unlock(&_rwlock);

                    return true;
                }
            }
            pthread_rwlock_unlock(&_rwlock);
            return false;
        }
        // 获取存放的所有信息
        bool GetAll(std::vector<BackupInfo> &array)
        {
            for (auto it = _table.begin(); it != _table.end(); it++)
            {
                array.push_back(it->second);
            }

            return true;
        }

    private:
        std::string _backup_file;                           // 持久化存储文件
        std::unordered_map<std::string, BackupInfo> _table; // 内存中以hash表存储
        pthread_rwlock_t _rwlock;                           // 读写锁——读共享，写互斥
    };
}
#endif